package cn.iocoder.an.module.mold.utils;

import lombok.Data;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 模具状态管理工具类
 * 管理模具的出入库、使用、维修、保养、复检等多维度状态转换
 */
public class MoldStateUtils {

    // ==================== 状态枚举定义 ====================

    /**
     * 出入库状态
     */
    public enum InventoryStatus {
        OUT_STOCK(0, "出库"),
        IN_STOCK(1, "在库");

        private final int code;
        private final String description;

        InventoryStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static InventoryStatus fromCode(int code) {
            return Arrays.stream(values())
                    .filter(status -> status.code == code)
                    .findFirst()
                    .orElse(IN_STOCK);
        }
    }

    /**
     * 使用状态
     */
    public enum UsageStatus {
        IDLE(0, "空闲"),
        IN_USE(1, "使用中"),
        UNAVAILABLE(2, "不可使用");

        private final int code;
        private final String description;

        UsageStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static UsageStatus fromCode(int code) {
            return Arrays.stream(values())
                    .filter(status -> status.code == code)
                    .findFirst()
                    .orElse(IDLE);
        }
    }

    /**
     * 任务状态（适用于维修、保养、复检）
     */
    public enum TaskStatus {
        NONE(0, "无维修任务"),
        PENDING_DISPATCH(2, "待接收"),
        IN_PROGRESS(3, "进行中"),
        PENDING_REVIEW(4, "待审核");

        private final int code;
        private final String description;

        TaskStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static TaskStatus fromCode(int code) {
            return Arrays.stream(values())
                    .filter(status -> status.code == code)
                    .findFirst()
                    .orElse(NONE);
        }
    }

    // ==================== 状态对象定义 ====================

    /**
     * 模具状态对象
     */
    @Data
    public static class MoldState {
        private final InventoryStatus inventory;      // a: 出入库状态
        private final UsageStatus usage;              // b: 使用状态
        private final TaskStatus repair;              // c: 维修状态
        private final TaskStatus maintenance;         // d: 保养状态
        private final TaskStatus reinspection;        // e: 复检状态

        /**
         * 转换为状态编码字符串 a_b_c_d_e
         */
        public String toCode() {
            return String.format("%d_%d_%d_%d_%d",
                    inventory.getCode(), usage.getCode(),
                    repair.getCode(), maintenance.getCode(), reinspection.getCode());
        }

        /**
         * 从状态编码创建对象
         */
        public static MoldState fromCode(String code) {
            try {
                String[] parts = code.split("_");
                return new MoldState(
                        InventoryStatus.fromCode(Integer.parseInt(parts[0])),
                        UsageStatus.fromCode(Integer.parseInt(parts[1])),
                        TaskStatus.fromCode(Integer.parseInt(parts[2])),
                        TaskStatus.fromCode(Integer.parseInt(parts[3])),
                        TaskStatus.fromCode(Integer.parseInt(parts[4]))
                );
            } catch (Exception e) {
                throw new IllegalArgumentException("无效的状态编码: " + code, e);
            }
        }

        /**
         * 获取状态的文字描述
         */
        public String getDescription() {
            List<String> descriptions = new ArrayList<>();
            descriptions.add(inventory.getDescription());
            descriptions.add(usage.getDescription());

            if (repair != TaskStatus.NONE) {
                descriptions.add("维修" + repair.getDescription());
            }
            if (maintenance != TaskStatus.NONE) {
                descriptions.add("保养" + maintenance.getDescription());
            }
            if (reinspection != TaskStatus.NONE) {
                descriptions.add("复检" + reinspection.getDescription());
            }

            return String.join(" | ", descriptions);
        }

        /**
         * 检查是否有任何任务
         */
        public boolean hasAnyTask() {
            return repair != TaskStatus.NONE ||
                    maintenance != TaskStatus.NONE ||
                    reinspection != TaskStatus.NONE;
        }

        /**
         * 检查是否有进行中的任务
         */
        public boolean hasInProgressTask() {
            return repair == TaskStatus.IN_PROGRESS ||
                    maintenance == TaskStatus.IN_PROGRESS ||
                    reinspection == TaskStatus.IN_PROGRESS;
        }
    }

    // ==================== 转换规则定义 ====================

    /**
     * 状态转换规则
     */
    @Data
    private static class TransitionRule {
        private final Predicate<MoldState> sourceCondition;  // 源状态条件
        private final Predicate<MoldState> targetCondition;  // 目标状态条件
        private final boolean allowed;                       // 是否允许
        private final String reason;                         // 原因描述
        private final int priority;                          // 优先级（数字越小优先级越高）

        public boolean matches(MoldState from, MoldState to) {
            return sourceCondition.test(from) && targetCondition.test(to);
        }
    }

    /**
     * 验证结果
     */
    @Data
    public static class ValidationResult {
        private final boolean allowed;
        private final String message;

        public static ValidationResult allowed(String message) {
            return new ValidationResult(true, message);
        }

        public static ValidationResult denied(String message) {
            return new ValidationResult(false, message);
        }
    }

    // ==================== 核心规则配置 ====================

    /**
     * 状态转换规则配置
     * 优先级说明：数字越小优先级越高，匹配到规则后立即返回
     */
    private static final List<TransitionRule> TRANSITION_RULES = Arrays.asList(
            // ========== 高优先级禁止规则 ==========

            // 规则1: 有任务时不能切换到使用中
            new TransitionRule(
                    state -> state.hasAnyTask(),                    // 条件：有任意任务
                    state -> state.getUsage() == UsageStatus.IN_USE, // 目标：切换到使用中
                    false,
                    "模具有未完成任务，无法开始使用",
                    1
            ),

            // 规则2: 使用中时不能创建任务
            new TransitionRule(
                    state -> state.getUsage() == UsageStatus.IN_USE, // 条件：使用中
                    MoldState::hasAnyTask,                          // 目标：创建了任务
                    false,
                    "模具使用中，无法创建新任务",
                    1
            ),

            // 规则3: 使用中不能出库
            new TransitionRule(
                    state -> state.getUsage() == UsageStatus.IN_USE, // 条件：使用中
                    state -> state.getInventory() == InventoryStatus.IN_STOCK, // 目标：出库
                    false,
                    "模具使用中，无法出库",
                    1
            ),

            // 规则4: 出库状态不能有进行中的任务
            new TransitionRule(
                    state -> state.getInventory() == InventoryStatus.OUT_STOCK, // 条件：出库
                    MoldState::hasInProgressTask,                    // 目标：有进行中任务
                    false,
                    "模具已出库，不能有进行中的任务",
                    1
            ),

            // ========== 允许规则 ==========

            // 规则5: 允许空闲无任务时开始使用（出库空闲）
            new TransitionRule(
                    state -> state.getUsage() == UsageStatus.IDLE &&state.getInventory() == InventoryStatus.OUT_STOCK && !state.hasAnyTask(),
                    state -> state.getUsage() == UsageStatus.IN_USE,
                    true,
                    "允许开始使用模具",
                    2
            ),

            // 规则6: 允许停止使用
            new TransitionRule(
                    state -> state.getUsage() == UsageStatus.IN_USE,
                    state -> state.getUsage() == UsageStatus.IDLE,
                    true,
                    "允许停止使用模具",
                    2
            ),

            // 规则7: 允许创建任务（非使用中状态）
/*            new TransitionRule(
                    state -> state.getUsage() != UsageStatus.IN_USE,
                    state -> true, // 任何目标状态（在创建任务时具体检查）
                    true,
                    "允许创建任务",
                    3
            )*/
            // 规则8: 允许入库（仅当模具处于出库状态且未在使用中时）
            new TransitionRule(
                    state -> state.getInventory() == InventoryStatus.OUT_STOCK &&
                            state.getUsage() != UsageStatus.IN_USE,
                    state -> state.getInventory() == InventoryStatus.IN_STOCK,
                    true,
                    "允许入库",
                    3
            ),
            // 规则8: 允许出库（仅当模具处于入库状态且未在使用中时）
            new TransitionRule(
                    state -> state.getInventory() == InventoryStatus.IN_STOCK &&
                            state.getUsage() != UsageStatus.IN_USE,
                    state -> state.getInventory() == InventoryStatus.OUT_STOCK,
                    true,
                    "允许入库",
                    3
            )

    );

    // 按优先级排序
    static {
        TRANSITION_RULES.sort(Comparator.comparingInt(TransitionRule::getPriority));
    }

    // ==================== 公共API方法 ====================

    /**
     * 验证状态转换是否允许
     *
     * @param fromState 源状态（编码或对象）
     * @param toState 目标状态（编码或对象）
     * @return 验证结果
     */
    public static ValidationResult validateTransition(Object fromState, Object toState) {
        MoldState from = convertToStateObject(fromState);
        MoldState to = convertToStateObject(toState);

        for (TransitionRule rule : TRANSITION_RULES) {
            if (rule.matches(from, to)) {
                return rule.isAllowed() ?
                        ValidationResult.allowed(rule.getReason()) :
                        ValidationResult.denied(rule.getReason());
            }
        }

        // 默认禁止未知转换
        return ValidationResult.denied("未知状态转换，默认禁止");
    }

    /**
     * 获取所有允许的目标状态
     *
     * @param currentState 当前状态
     * @return 允许的目标状态列表
     */
    public static List<MoldState> getAllowedTargetStates(Object currentState) {
        MoldState current = convertToStateObject(currentState);
        List<MoldState> allowedStates = new ArrayList<>();

        // 遍历所有可能的状态组合
        for (InventoryStatus inv : InventoryStatus.values()) {
            for (UsageStatus usage : UsageStatus.values()) {
                for (TaskStatus repair : TaskStatus.values()) {
                    for (TaskStatus maintenance : TaskStatus.values()) {
                        for (TaskStatus reinspection : TaskStatus.values()) {
                            MoldState target = new MoldState(inv, usage, repair, maintenance, reinspection);
                            if (validateTransition(current, target).isAllowed()) {
                                allowedStates.add(target);
                            }
                        }
                    }
                }
            }
        }

        return allowedStates;
    }

    /**
     * 获取允许的操作列表（用于UI展示）
     *
     * @param currentState 当前状态
     * @return 允许的操作描述列表
     */
    public static List<String> getAllowedOperations(Object currentState) {
        MoldState current = convertToStateObject(currentState);
        List<String> operations = new ArrayList<>();

        // 检查各种操作是否允许
        if (canStartUsing(current)) {
            operations.add("开始使用");
        }
        if (canStopUsing(current)) {
            operations.add("停止使用");
        }
        if (canCreateRepairTask(current)) {
            operations.add("创建维修任务");
        }
        if (canCreateMaintenanceTask(current)) {
            operations.add("创建保养任务");
        }
        if (canCreateReinspectionTask(current)) {
            operations.add("创建复检任务");
        }
        if (canMoveToStock(current)) {
            operations.add("入库");
        }
        if (canMoveOutStock(current)) {
            operations.add("出库");
        }

        return operations;
    }

    /**
     * 创建开始使用状态
     */
    public static MoldState createInUseState(MoldState current) {
        return new MoldState(
                current.getInventory(),
                UsageStatus.IN_USE,
                current.getRepair(),
                current.getMaintenance(),
                current.getReinspection()
        );
    }

    /**
     * 创建停止使用状态
     */
    public static MoldState createIdleState(MoldState current) {
        return new MoldState(
                current.getInventory(),
                UsageStatus.IDLE,
                current.getRepair(),
                current.getMaintenance(),
                current.getReinspection()
        );
    }

    /**
     * 创建维修任务状态
     */
    public static MoldState createRepairTaskState(MoldState current, TaskStatus repairStatus) {
        return new MoldState(
                current.getInventory(),
                current.getUsage(),
                repairStatus,
                current.getMaintenance(),
                current.getReinspection()
        );
    }

    /**
     * 创建保养任务状态
     */
    public static MoldState createMaintenanceTaskState(MoldState current, TaskStatus maintenanceStatus) {
        return new MoldState(
                current.getInventory(),
                current.getUsage(),
                current.getRepair(),
                maintenanceStatus,
                current.getReinspection()
        );
    }

    /**
     * 创建复检任务状态
     */
    public static MoldState createReinspectionTaskState(MoldState current, TaskStatus reinspectionStatus) {
        return new MoldState(
                current.getInventory(),
                current.getUsage(),
                current.getRepair(),
                current.getMaintenance(),
                reinspectionStatus
        );
    }

    /**
     * 创建入库状态
     */
    public static MoldState createInStockState(MoldState current) {
        return new MoldState(
                InventoryStatus.IN_STOCK,
                current.getUsage(),
                current.getRepair(),
                current.getMaintenance(),
                current.getReinspection()
        );
    }

    /**
     * 创建出库状态
     */
    public static MoldState createOutStockState(MoldState current) {
        return new MoldState(
                InventoryStatus.OUT_STOCK,
                current.getUsage(),
                current.getRepair(),
                current.getMaintenance(),
                current.getReinspection()
        );
    }

    // ==================== 私有辅助方法 ====================

    private static MoldState convertToStateObject(Object state) {
        if (state instanceof MoldState) {
            return (MoldState) state;
        } else if (state instanceof String) {
            return MoldState.fromCode((String) state);
        } else {
            throw new IllegalArgumentException("不支持的状态类型: " + state.getClass());
        }
    }

    private static boolean canStartUsing(MoldState state) {
        MoldState target = createInUseState(state);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canStopUsing(MoldState state) {
        MoldState target = createIdleState(state);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canCreateRepairTask(MoldState state) {
        MoldState target = createRepairTaskState(state, TaskStatus.PENDING_DISPATCH);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canCreateMaintenanceTask(MoldState state) {
        MoldState target = createMaintenanceTaskState(state, TaskStatus.PENDING_DISPATCH);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canCreateReinspectionTask(MoldState state) {
        MoldState target = createReinspectionTaskState(state, TaskStatus.PENDING_DISPATCH);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canMoveToStock(MoldState state) {
        MoldState target = createInStockState(state);
        return validateTransition(state, target).isAllowed();
    }

    private static boolean canMoveOutStock(MoldState state) {
        MoldState target = createOutStockState(state);
        return validateTransition(state, target).isAllowed();
    }
}